package com.example.sanguogameserver.logic;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.example.sanguogameserver.ai.enums.AiType;
import com.example.sanguogameserver.ai.logic.AiLogic;
import com.example.sanguogameserver.ai.logic.AttackLogic;
import com.example.sanguogameserver.ai.model.Position;
import com.example.sanguogameserver.ai.model.TreeGeneral;
import com.example.sanguogameserver.ai.model.TreeSkill;
import com.example.sanguogameserver.consts.SanGuoConst;
import com.example.sanguogameserver.dto.CastSkillRespDTO;
import com.example.sanguogameserver.dto.GeneralDeBuffer;
import com.example.sanguogameserver.dto.battle.*;
import com.example.sanguogameserver.entity.*;
import com.example.sanguogameserver.enums.BattleEnum;
import com.example.sanguogameserver.enums.EnableEnum;
import com.example.sanguogameserver.enums.OnlineEnum;
import com.example.sanguogameserver.enums.TreePlayerTypeEnum;
import com.example.sanguogameserver.logic.generalStatus.GeneraStatusInterface;
import com.example.sanguogameserver.service.*;
import com.example.sanguogameserver.util.AuthUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class BattleLogic {
    @Autowired
    private AttackTaskService attackTaskService;
    @Autowired
    private TerritoryService territoryService;
    @Autowired
    private PlayerGeneralService playerGeneralService;
    @Autowired
    private GeneralTypeService generalTypeService;
    @Autowired
    private SkillPlayerGeneralService skillPlayerGeneralService;
    @Autowired
    private SkillService skillService;
    @Autowired
    private PlayerService playerService;

    public BattleDetail getBattleDetail(Integer id) {
        // 初始化 trees
        // 加载领地信息
        AttackTask attackTask = attackTaskService.getById(id);
        Player attackPlayer = playerService.getById(attackTask.getAttackPlayerId());
        Player beAttackPlayer = playerService.getById(attackTask.getBeAttackPlayerId());

        if (attackTask.getAttackDetailJson() != null) {
            BattleDetail attackDetailJson = attackTask.getAttackDetailJson();
            AttackTaskInfo attackTaskInfo = new AttackTaskInfo();
            BeanUtils.copyProperties(attackTask, attackTaskInfo);
            attackTaskInfo.setAttackPlayer(attackPlayer);
            attackTaskInfo.setBeAttackPlayer(beAttackPlayer);
            attackDetailJson.setAttackTask(attackTaskInfo);
            return attackDetailJson;
        }

        // 两名玩家
        // 领地
        Territory territory = territoryService.getById(attackTask.getBeAttackTerritoryId());
        BattleDetail battleDetail = territory.getTreeData();
        battleDetail.setCurrentPlayerType(TreePlayerTypeEnum.red);
        List<BattleTreeInfoRow> trees = battleDetail.getTrees();
        for (int i = 0; i < trees.size(); i++) {
            BattleTreeInfoRow battleTreeInfoRow = trees.get(i);
            battleTreeInfoRow.setRow(i);
            for (int j = 0; j < battleTreeInfoRow.getTreeInfoColumns().size(); j++) {
                BattleTreeInfoColumn battleTreeInfoColumn = battleTreeInfoRow.getTreeInfoColumns().get(j);
                // 清除除了地形,其他数据
                battleTreeInfoColumn.init();
                battleTreeInfoColumn.setRow(i);
                battleTreeInfoColumn.setColumn(j);
            }
        }

        // 布置武将
        // 红方攻击武将
        List<PlayerGeneral> redPlayerGenerals = playerGeneralService.getByTaskId(id);

        // 假设红方是左边,蓝方是右边
        // 布置红方武将, FIXME 默认两列,后续优化
        // 左上角是起点
        // 起点
        int row = 0;
        int column = 0;
        // 最大一行放五个
        int maxColumnGeneral = 5;
        for (int i = 0; i < redPlayerGenerals.size(); i++) {
            PlayerGeneral playerGeneral = redPlayerGenerals.get(i);
            BattleTreeInfoColumn battleTreeInfoColumn = trees.get(row).getTreeInfoColumns().get(column);

            while (!battleTreeInfoColumn.getIsMove()) {
                // 不能移动,获取下一个
                column++;
                if (column > maxColumnGeneral) {
                    row++;
                    column = 0;
                }
                battleTreeInfoColumn = trees.get(row).getTreeInfoColumns().get(column);
            }

            // 设置武将
            TreeGeneral treeGeneral = transPlayerGeneral(playerGeneral, TreePlayerTypeEnum.red);
            battleTreeInfoColumn.setPlayerTreeGeneral(treeGeneral);
            battleTreeInfoColumn.setTreePlayerType(treeGeneral.getTreePlayerType());
            battleTreeInfoColumn.setAi(false);
            // 离线或者没有进入
            if (attackPlayer.getOnline() != OnlineEnum.Offline || attackTask.getAttackIsEnter() == EnableEnum.False) {
                BattleUtil.setAi(battleTreeInfoColumn, true, AiType.activeAttack);
            }
            column++;
            if (column == maxColumnGeneral) {
                row++;
                column = 0;
            }
        }

        // 蓝方 守城武将
        List<PlayerGeneral> bluePlayerGenerals = playerGeneralService.getByTerritoryId(territory.getId());
        // 蓝方武将默认右下角
        row = trees.size() - 1;
        column = trees.get(trees.size() - 1).getTreeInfoColumns().size() - 1;
        for (int i = 0; i < bluePlayerGenerals.size(); i++) {
            PlayerGeneral playerGeneral = bluePlayerGenerals.get(i);
            BattleTreeInfoColumn battleTreeInfoColumn = trees.get(row).getTreeInfoColumns().get(column);
            while (!battleTreeInfoColumn.getIsMove()) {
                // 不能移动,获取下一个
                column--;
                BattleTreeInfoRow battleTreeInfoRow = trees.get(row);
                if (column == battleTreeInfoRow.getTreeInfoColumns().size() - (maxColumnGeneral + 1)) {
                    row--;
                    column = trees.get(row).getTreeInfoColumns().size() - 1;
                }
                battleTreeInfoColumn = trees.get(row).getTreeInfoColumns().get(column);
            }
            // 设置武将
            TreeGeneral treeGeneral = transPlayerGeneral(playerGeneral, TreePlayerTypeEnum.blue);
            battleTreeInfoColumn.setPlayerTreeGeneral(treeGeneral);
            battleTreeInfoColumn.setTreePlayerType(treeGeneral.getTreePlayerType());
            battleTreeInfoColumn.setAi(false);
            // 离线或者没有进入
            if (beAttackPlayer.getOnline() != OnlineEnum.Offline || attackTask.getBeAttackIsEnter() == EnableEnum.False) {
                BattleUtil.setAi(battleTreeInfoColumn, true, AiType.passiveAttack);

            }
            column--;
            if (column == trees.get(trees.size() - 1).getTreeInfoColumns().size() - (maxColumnGeneral + 1)) {
                row--;
                column = trees.get(trees.size() - 1).getTreeInfoColumns().size() - 1;
            }
        }
        AttackTaskInfo attackTaskInfo = new AttackTaskInfo();
        BeanUtils.copyProperties(attackTask, attackTaskInfo);
        attackTaskInfo.setAttackPlayer(attackPlayer);
        attackTaskInfo.setBeAttackPlayer(beAttackPlayer);
        battleDetail.setAttackTask(attackTaskInfo);
        attackTask.setAttackDetailJson(battleDetail);
        attackTaskService.updateById(attackTask);
        // 设置Ai
        return battleDetail;
    }

    private TreeGeneral transPlayerGeneral(PlayerGeneral playerGeneral, TreePlayerTypeEnum treePlayerTypeEnum) {
        TreeGeneral treeGeneral = new TreeGeneral();
        treeGeneral.setId(playerGeneral.getId());
        treeGeneral.setPlayId(playerGeneral.getPlayId());
        treeGeneral.setGeneralId(playerGeneral.getGeneralId());
        treeGeneral.setCurrentHealth(playerGeneral.getHealth());
        treeGeneral.setHealth(playerGeneral.getHealth());
        treeGeneral.setCurrentMp(playerGeneral.getMp());
        treeGeneral.setMp(playerGeneral.getMp());
        treeGeneral.setGeneralCategoryEnum(playerGeneral.getGeneralCategory());
        treeGeneral.setGeneralName(playerGeneral.getGeneralName());
        treeGeneral.setCurrentAttack(playerGeneral.getAttack());
        treeGeneral.setAttack(playerGeneral.getAttack());
        treeGeneral.setCurrentDefense(playerGeneral.getDefense());
        treeGeneral.setDefense(playerGeneral.getDefense());
        treeGeneral.setCurrentSpellStrength(playerGeneral.getSpellStrength());
        treeGeneral.setSpellStrength(playerGeneral.getSpellStrength());
        treeGeneral.setCurrentDodge(playerGeneral.getDodge());
        treeGeneral.setDodge(playerGeneral.getDodge());
        treeGeneral.setCurrentCrit(playerGeneral.getCrit());
        treeGeneral.setCrit(playerGeneral.getCrit());
        treeGeneral.setStar(playerGeneral.getStar());
        treeGeneral.setLevel(playerGeneral.getLevel());
        treeGeneral.setGeneralType(playerGeneral.getGeneralType());
        treeGeneral.setMutationType(playerGeneral.getMutationType());
        // 获取武将类别信息
        GeneralType generalType = generalTypeService.getGeneralByCategoryAndName(playerGeneral.getGeneralCategory(), playerGeneral.getGeneralType());
        treeGeneral.setRange(generalType.getRange());
        treeGeneral.setRangeCount(generalType.getRangeCount());
        treeGeneral.setSkillRangeCount(generalType.getSkillRangeCount());
        treeGeneral.setMoveCount(generalType.getMoveCount());
        treeGeneral.setTreePlayerType(treePlayerTypeEnum);
        // 获取技能
        List<SkillPlayerGeneral> skillPlayerGenerals = skillPlayerGeneralService.listByPlayerGeneralId(playerGeneral.getId());
        List<TreeSkill> treeSkills = skillPlayerGenerals.stream().map(this::transSkill).toList();
        treeGeneral.setSkills(treeSkills);
        treeGeneral.setAi(false);
        return treeGeneral;
    }

    private TreeSkill transSkill(SkillPlayerGeneral skillPlayerGeneral) {
        Skill skill = skillService.getByCode(skillPlayerGeneral.getSkillCode());
        TreeSkill treeSkill = new TreeSkill();

        treeSkill.setSkill(skill);
        return treeSkill;
    }

    public BattleDetail go(BattleGoReq battleGoReq) {
        AttackTask attackTask = attackTaskService.getById(battleGoReq.getAttackTaskId());
        BattleDetail battleDetail = attackTask.getAttackDetailJson();

        // 移动
        List<BattleTreeInfoRow> trees = battleDetail.getTrees();
        BattleTreeInfoColumn oldTree = trees.get(battleGoReq.getOldRow()).getTreeInfoColumns().get(battleGoReq.getOldColumn());
        BattleTreeInfoColumn newTree = trees.get(battleGoReq.getNewRow()).getTreeInfoColumns().get(battleGoReq.getNewColumn());
        BattleTreeInfoColumn selectTree = trees.get(battleGoReq.getSelectRow()).getTreeInfoColumns().get(battleGoReq.getSelectColumn());
        oldTree.getPlayerTreeGeneral().setCurrentMoved(true);

        if (newTree != oldTree) {
            newTree.setPlayerTreeGeneral(oldTree.getPlayerTreeGeneral());
            newTree.setTreePlayerType(oldTree.getTreePlayerType());
            oldTree.setPlayerTreeGeneral(null);
            oldTree.setTreePlayerType(null);
        }


        BattleRoundInfo battleRoundInfo = new BattleRoundInfo();
        battleRoundInfo.setStepId(battleDetail.getStepId() + 1);
        battleRoundInfo.setRound(battleDetail.getRound());
        battleRoundInfo.setTreePlayerTypeEnum(battleGoReq.getAttackerType());

        AiRoundInfo aiRoundInfo = new AiRoundInfo();
        aiRoundInfo.setPlayerTreeGeneralId(newTree.getPlayerTreeGeneral().getId());
        aiRoundInfo.setOldRow(battleGoReq.getOldRow());
        aiRoundInfo.setOldColumn(battleGoReq.getOldColumn());
        aiRoundInfo.setNewRow(battleGoReq.getNewRow());
        aiRoundInfo.setNewColumn(battleGoReq.getNewColumn());
        aiRoundInfo.setSelectRow(battleGoReq.getSelectRow());
        aiRoundInfo.setSelectColumn(battleGoReq.getSelectColumn());
        aiRoundInfo.setTreeSkill(battleGoReq.getTreeSkill());
        battleRoundInfo.setAiRoundInfo(aiRoundInfo);


        // 移动完了,是否要攻击
        if (battleGoReq.getTreeSkill() != null) {
            // 攻击
            List<CastSkillRespDTO> attack = AttackLogic.attack(newTree, selectTree, trees, battleGoReq.getTreeSkill());
            // 只有第一个反击

            CastSkillRespDTO castSkillRespDTO = attack.getFirst();
            AiLogic aiLogic = new AiLogic(battleDetail.trees, castSkillRespDTO.getAttackTarget().getTreePlayerType());
            List<Position> attackPosition = aiLogic.getAttackPosition(castSkillRespDTO.getAttackTarget().getPlayerTreeGeneral().getRange(), castSkillRespDTO.getAttackTarget().getPlayerTreeGeneral().getRangeCount(),
                    castSkillRespDTO.getAttackTarget());

            Position position = new Position(newTree.getColumn(), newTree.getRow());

            //FIXME 眩晕,不会反击
            // 攻击距离,包含了对方的,就会反击
            if (attackPosition.contains(position)) {
                List<CastSkillRespDTO> counterattackCastSkill = AttackLogic.attack(castSkillRespDTO.getAttackTarget(), newTree, trees, AttackLogic.normalAttack(castSkillRespDTO.getAttackTarget().getPlayerTreeGeneral(), newTree.getPlayerTreeGeneral()));
                castSkillRespDTO.setCounterattackCastSkill(counterattackCastSkill);
            }
            battleRoundInfo.setCastSkills(attack);


        }
        battleDetail.getBattleRoundInfos().add(battleRoundInfo);
        BattleRoundInfo battleRoundInfoGameOver = detectionDeadOrGameOver(battleDetail);
        if (battleRoundInfoGameOver != null) {
            // 战斗结束
            battleDetail.getBattleRoundInfos().add(battleRoundInfoGameOver);
            gameOver(battleRoundInfoGameOver, battleDetail, attackTask);
        }

        attackTask.setAttackDetailJson(battleDetail);
        attackTaskService.updateById(attackTask);
        return battleDetail;
    }

    public void gameOver(BattleRoundInfo gameOverbattleRoundInfo, BattleDetail battleDetail, AttackTask attackTask) {
        // 战斗结束
        battleDetail.setGameOver(gameOverbattleRoundInfo.isGameOver());
        battleDetail.setWin(gameOverbattleRoundInfo.getWin());
        attackTask.setWin(gameOverbattleRoundInfo.getWin());
        attackTask.setIsBattle(BattleEnum.theBattleIsOver);


        Territory territory = territoryService.getById(attackTask.getBeAttackTerritoryId());
        // 进攻方胜利
        if (attackTask.getWin() == 1) {
            Integer attackPlayerId = attackTask.getAttackPlayerId();
            List<PlayerGeneral> playerGenerals = playerGeneralService.getByTaskId(attackTask.getId());

            for (PlayerGeneral playerGeneral : playerGenerals) {
                playerGeneral.setAttackTaskId(null);
                playerGeneral.setTerritoryId(territory.getId());
                playerGeneral.setTerritoryIndex(playerGeneral.getAttackTaskIndex());
                playerGeneral.setAttackTaskIndex(null);
                playerGeneralService.updateById(playerGeneral);
            }

            territory.setPlayId(attackPlayerId);
            territory.setPlayerGeneralId(playerGenerals.getFirst().getId());
            territoryService.updateById(territory);
        }
    }


    public BattleDetail aiGo(Integer attackTaskId, TreePlayerTypeEnum treePlayerTypeEnum) {
        AttackTask attackTask = attackTaskService.getById(attackTaskId);
        BattleDetail battleDetail = attackTask.getAttackDetailJson();

        return aiGo(treePlayerTypeEnum, battleDetail, attackTask);
    }

    private BattleDetail aiGo(TreePlayerTypeEnum treePlayerTypeEnum, BattleDetail battleDetail, AttackTask attackTask) {
        AiLogic aiLogic = new AiLogic(battleDetail.trees, treePlayerTypeEnum);
        BattleRoundInfo battleRoundInfo = aiLogic.aiGo();
        battleRoundInfo.setStepId(battleDetail.getStepId() + 1);
        battleRoundInfo.setRound(battleDetail.getRound());
        battleRoundInfo.setTreePlayerTypeEnum(treePlayerTypeEnum);
        battleRoundInfo.setAi(true);
        battleDetail.getBattleRoundInfos().add(battleRoundInfo);
        attackTask.setAttackDetailJson(battleDetail);
        attackTaskService.updateById(attackTask);
        return battleDetail;
    }

    public boolean aiLogic(BattleDetail battleDetail, AttackTask attackTask) {
        TreePlayerTypeEnum currentPlayerType = battleDetail.getCurrentPlayerType();
        if (currentPlayerType == TreePlayerTypeEnum.red && !battleDetail.isAttackIsAi()) {
            return false;
        }
        if (currentPlayerType == TreePlayerTypeEnum.blue && !battleDetail.isBeAttackIsAi()) {
            return false;
        }
        List<BattleTreeInfoColumn> battleTreeInfoColumns = battleDetail.findWhere(column -> {
            // 是当前回合的武将,并且没有移动
            return column.getTreePlayerType() != null
                    && column.getTreePlayerType() == currentPlayerType;
        });
        // 一共有多少武将
        int treeInfoCoumnSize = battleTreeInfoColumns.size();
        for (int i = 0; i < treeInfoCoumnSize; i++) {
            battleDetail = aiGo(currentPlayerType, battleDetail, attackTask);
        }
        return true;
    }

    public BattleDetail startBlueRound(Integer id) {
        AttackTask attackTask = attackTaskService.getById(id);
        BattleDetail battleDetail = attackTask.getAttackDetailJson();
        BattleRoundInfo battleRoundInfo = startRound(battleDetail, TreePlayerTypeEnum.blue);
        battleDetail.getBattleRoundInfos().add(battleRoundInfo);
        battleDetail.setRoundRemainderDate(getRoundRemainderDate());
        battleDetail.setCurrentPlayerType(TreePlayerTypeEnum.blue);
        boolean isAi = aiLogic(battleDetail, attackTask);
        if (isAi) {
            battleRoundInfo.setRoundAi(true);
        }
        attackTask.setAttackDetailJson(battleDetail);
        attackTaskService.updateById(attackTask);
        if (isAi) {
            battleDetail = startRedRound(id);
        }
        return battleDetail;
    }

    public BattleDetail startRedRound(Integer id) {
        AttackTask attackTask = attackTaskService.getById(id);
        BattleDetail battleDetail = attackTask.getAttackDetailJson();
        battleDetail.setRound(battleDetail.getRound() + 1);

        BattleRoundInfo battleRoundInfo = startRound(battleDetail, TreePlayerTypeEnum.red);
        battleDetail.getBattleRoundInfos().add(battleRoundInfo);
        battleDetail.setRoundRemainderDate(getRoundRemainderDate());
        battleDetail.setCurrentPlayerType(TreePlayerTypeEnum.red);
        boolean isAi = aiLogic(battleDetail, attackTask);
        if (isAi) {
            battleRoundInfo.setRoundAi(true);
        }
        attackTask.setAttackDetailJson(battleDetail);
        attackTaskService.updateById(attackTask);

        BattleRoundInfo battleRoundInfoGameOver = detectionDeadOrGameOver(battleDetail);
        if (battleRoundInfoGameOver != null) {
            // 战斗结束
            battleDetail.setStepId(battleDetail.getStepId() + 1);
            battleRoundInfoGameOver.setStepId(battleRoundInfoGameOver.getStepId() + 1);
            battleDetail.getBattleRoundInfos().add(battleRoundInfoGameOver);
            gameOver(battleRoundInfoGameOver, battleDetail, attackTask);
            attackTask.setAttackDetailJson(battleDetail);
            attackTaskService.updateById(attackTask);
            return battleDetail;
        }

        if (isAi) {
            battleDetail = startBlueRound(id);
        }
        return battleDetail;
    }

    public BattleRoundInfo startRound(BattleDetail battleDetail, TreePlayerTypeEnum treePlayerTypeEnum) {
        BattleRoundInfo battleRoundInfo = new BattleRoundInfo();
        battleRoundInfo.setStepId(battleDetail.getStepId() + 1);
        battleRoundInfo.setRound(battleDetail.getRound());
        battleRoundInfo.setRoundInit(true);
        battleRoundInfo.setTreePlayerTypeEnum(treePlayerTypeEnum);

        List<CastSkillRespDTO> castSkills = new ArrayList<>();
        List<BattleTreeInfoRow> trees = battleDetail.getTrees();
        List<BattleTreeInfoColumn> treeInfoColumns = new ArrayList<BattleTreeInfoColumn>();

        for (BattleTreeInfoRow tree : trees) {
            for (BattleTreeInfoColumn treeInfoColumn : tree.getTreeInfoColumns()) {
                if (treeInfoColumn.getPlayerTreeGeneral() != null) {
                    treeInfoColumn.getPlayerTreeGeneral().setCurrentMoved(false);
                }
                // 不是空的
                if (treeInfoColumn.getTreePlayerType() != null && treeInfoColumn.getTreePlayerType() == treePlayerTypeEnum) {
                    treeInfoColumns.add(treeInfoColumn);
                }
            }
        }
        // 武将初始化可以移动状态
        for (BattleTreeInfoColumn treeInfoColumn : treeInfoColumns) {
            TreeGeneral playerTreeGeneral = treeInfoColumn.getPlayerTreeGeneral();

            playerTreeGeneral.setCurrentMoved(false);
            playerTreeGeneral.setCurrentImprisonment(false);
            playerTreeGeneral.setCurrentBanReplayHealth(false);
            playerTreeGeneral.setCurrentVertigo(false);
            // buffer
            for (GeneralDeBuffer buffer : playerTreeGeneral.getBuffer()) {
                if (buffer.getCount() >= 0) {
                    GeneraStatusInterface generaStatusInterface = ((Map<String, GeneraStatusInterface>) SpringUtil.getBean("generaStatusInterfaces")).get(buffer.getGeneralStatusType().name());

                    List<CastSkillRespDTO> castSkillRespDTOS = generaStatusInterface.trigger(treeInfoColumn, trees);
                    castSkills.addAll(castSkillRespDTOS);
                    buffer.setCount(buffer.getCount() - 1);
                }
            }
            // 去除次数为0的buffer
            playerTreeGeneral.setBuffer(playerTreeGeneral.getBuffer().stream().filter(item -> item.getCount() <= 0).toList());
        }

        battleRoundInfo.setCastSkills(castSkills);
        return battleRoundInfo;
    }


    @Transactional
    public BattleDetail updatePlayerGeneralSort(UpdatePlayerGeneralSortReq updatePlayerGeneralSortReq) {
        // 当前武将类型
        AttackTask attackTask = attackTaskService.getById(updatePlayerGeneralSortReq.getAttackTaskId());
        TreePlayerTypeEnum treePlayerTypeEnum = getTreePlayerType(attackTask);
        BattleDetail battleDetail = attackTask.getAttackDetailJson();
        List<BattleTreeInfoRow> trees = battleDetail.getTrees();
        BattleTreeInfoColumn exchangePlayerGeneralBattleTreeInfoColumn = new BattleTreeInfoColumn();
        BattleTreeInfoColumn beExchangePlayerGeneralBattleTreeInfoColumn = new BattleTreeInfoColumn();
        for (BattleTreeInfoRow tree : trees) {
            for (BattleTreeInfoColumn treeInfoColumn : tree.getTreeInfoColumns()) {
                // 不是空的
                if (treeInfoColumn.getTreePlayerType() != null) {
                    if (treeInfoColumn.getTreePlayerType() == treePlayerTypeEnum && treeInfoColumn.getPlayerTreeGeneral().getId().equals(updatePlayerGeneralSortReq.getExchangePlayerGeneralId())) {
                        exchangePlayerGeneralBattleTreeInfoColumn = treeInfoColumn;
                    } else if (treeInfoColumn.getTreePlayerType() == treePlayerTypeEnum && treeInfoColumn.getPlayerTreeGeneral().getId().equals(updatePlayerGeneralSortReq.getBeExchangePlayerGeneralId())) {
                        beExchangePlayerGeneralBattleTreeInfoColumn = treeInfoColumn;
                    }
                }
            }
        }

        // 两个武将交换位置交换
        TreeGeneral tempTypeTreeGeneral = exchangePlayerGeneralBattleTreeInfoColumn.getPlayerTreeGeneral();
        TreePlayerTypeEnum tempTreePlayerType = exchangePlayerGeneralBattleTreeInfoColumn.getTreePlayerType();
        exchangePlayerGeneralBattleTreeInfoColumn.setPlayerTreeGeneral(beExchangePlayerGeneralBattleTreeInfoColumn.getPlayerTreeGeneral());
        exchangePlayerGeneralBattleTreeInfoColumn.setTreePlayerType(beExchangePlayerGeneralBattleTreeInfoColumn.getTreePlayerType());
        beExchangePlayerGeneralBattleTreeInfoColumn.setTreePlayerType(tempTreePlayerType);
        beExchangePlayerGeneralBattleTreeInfoColumn.setPlayerTreeGeneral(tempTypeTreeGeneral);

        PlayerGeneral exChangePlayerGeneral = playerGeneralService.getById(updatePlayerGeneralSortReq.getExchangePlayerGeneralId());
        PlayerGeneral beExChangePlayerGeneral = playerGeneralService.getById(updatePlayerGeneralSortReq.getBeExchangePlayerGeneralId());
        Integer tempAttackTaskIndex = exChangePlayerGeneral.getAttackTaskIndex();
        exChangePlayerGeneral.setAttackTaskIndex(beExChangePlayerGeneral.getAttackTaskIndex());
        beExChangePlayerGeneral.setAttackTaskIndex(tempAttackTaskIndex);
        playerGeneralService.updateById(exChangePlayerGeneral);
        playerGeneralService.updateById(beExChangePlayerGeneral);
        attackTask.setAttackDetailJson(battleDetail);
        attackTaskService.updateById(attackTask);
        return battleDetail;
    }


    private TreePlayerTypeEnum getTreePlayerType(AttackTask attackTask) {
        return BattleUtil.getTreePlayerType(attackTask, AuthUtil.getCurrPlayerId());
    }

    public BattleDetail start(StartBattleReq startBattleReq) {
        // 当前武将类型
        AttackTask attackTask = attackTaskService.getById(startBattleReq.getAttackTaskId());
        attackTask.setIsBattle(BattleEnum.inBattle);
        Player attackPlayer = playerService.getById(attackTask.getAttackPlayerId());
        Player beAttackPlayer = playerService.getById(attackTask.getBeAttackPlayerId());

        BattleDetail attackDetail = attackTask.getAttackDetailJson();
        // 设置ai
        List<BattleTreeInfoRow> trees = attackDetail.getTrees();
        for (BattleTreeInfoRow tree : trees) {
            for (BattleTreeInfoColumn treeInfoColumn : tree.getTreeInfoColumns()) {
                // 攻击方玩家
                if (treeInfoColumn.getTreePlayerType() != null && treeInfoColumn.getTreePlayerType() == TreePlayerTypeEnum.red) {
                    // 攻击玩家没进入,或者已离线
                    if (attackPlayer.getOnline() != OnlineEnum.online || attackTask.getAttackIsEnter() == EnableEnum.False) {
                        // 设置ai
                        attackDetail.setAttackIsAi(true);
                        BattleUtil.setAi(treeInfoColumn, true, AiType.activeAttack);
                    } else {
                        // 去掉ai
                        attackDetail.setAttackIsAi(false);
                        BattleUtil.setAi(treeInfoColumn, false, null);
                    }
                }
                if (treeInfoColumn.getTreePlayerType() != null && treeInfoColumn.getTreePlayerType() == TreePlayerTypeEnum.blue) {
                    // 攻击玩家没进入,或者已离线
                    if (beAttackPlayer.getOnline() != OnlineEnum.online || attackTask.getBeAttackIsEnter() == EnableEnum.False) {
                        // 设置ai
                        attackDetail.setBeAttackIsAi(true);
                        BattleUtil.setAi(treeInfoColumn, true, AiType.activeAttack);
                    } else {
                        // 去掉ai
                        attackDetail.setBeAttackIsAi(false);
                        BattleUtil.setAi(treeInfoColumn, false, null);
                    }
                }
            }
        }
        attackDetail.setRound(0);
        attackDetail.setCurrentPlayerType(TreePlayerTypeEnum.red);
        attackDetail.setRoundRemainderDate(getRoundRemainderDate());


        AttackTaskInfo attackTaskInfo = new AttackTaskInfo();
        BeanUtils.copyProperties(attackTask, attackTaskInfo);
        attackTaskInfo.setAttackPlayer(attackPlayer);
        attackTaskInfo.setBeAttackPlayer(beAttackPlayer);
        attackDetail.setAttackTask(attackTaskInfo);

        attackTask.setAttackDetailJson(attackDetail);
        attackTaskService.updateById(attackTask);
        return attackDetail;
    }

    // 获取剩余时间
    private Date getRoundRemainderDate() {
        DateTime date = DateUtil.date();
        date.offset(DateField.SECOND, SanGuoConst.attackRoundSecond);
        return date;
    }

    public List<Position> getCanMovePosition(GetCanMovePositionReq canMovePositionReq) {
        BattleDetail battleDetail = getBattleDetail(canMovePositionReq.getId());
        BattleTreeInfoColumn battleTreeInfoColumn = battleDetail.getTrees()
                .get(canMovePositionReq.getRow())
                .getTreeInfoColumns().get(canMovePositionReq.getColumn());

        AiLogic aiLogic = new AiLogic(battleDetail.trees, battleTreeInfoColumn.getTreePlayerType());
        List<BattleTreeInfoColumn> battleTreeInfoColumns = aiLogic.moveTreeRange(battleTreeInfoColumn);
        return battleTreeInfoColumns.stream().map(item -> {
            Position position = new Position();
            position.setX(item.getRow());
            position.setY(item.getColumn());
            return position;
        }).toList();
    }


    public List<Position> getCanAttackPosition(GetCanAttackPositionReq getCanAttackPositionReq) {
        BattleDetail battleDetail = getBattleDetail(getCanAttackPositionReq.getId());

        BattleTreeInfoColumn battleTreeInfoColumn = battleDetail.getTrees()
                .get(getCanAttackPositionReq.getRow())
                .getTreeInfoColumns().get(getCanAttackPositionReq.getColumn());

        BattleTreeInfoColumn newBattleTreeInfoColumn = battleDetail.getTrees()
                .get(getCanAttackPositionReq.getNewRow())
                .getTreeInfoColumns().get(getCanAttackPositionReq.getNewColumn());

        AiLogic aiLogic = new AiLogic(battleDetail.trees, battleTreeInfoColumn.getTreePlayerType());
        return aiLogic.getAttackPosition(battleTreeInfoColumn.getPlayerTreeGeneral().getRange(), battleTreeInfoColumn.getPlayerTreeGeneral().getRangeCount(),
                newBattleTreeInfoColumn);
    }

    public BattleRoundInfo detectionDeadOrGameOver(BattleDetail battleDetail) {
        List<BattleTreeInfoRow> trees = battleDetail.getTrees();
        BattleRoundInfo battleRoundInfo = null;
        // 进攻方是否死亡
        boolean redDead = true;
        // 防御方是否死亡
        boolean blueDead = true;

        for (BattleTreeInfoRow tree : trees) {
            for (BattleTreeInfoColumn treeInfoColumn : tree.getTreeInfoColumns()) {
                TreeGeneral treeGeneral = treeInfoColumn.getPlayerTreeGeneral();
                if (treeGeneral != null
                        && treeGeneral.getCurrentHealth() <= 0) {
                    treeInfoColumn.setDeadPlayerTreeGeneral(treeGeneral);
                    treeInfoColumn.setPlayerTreeGeneral(null);
                    treeInfoColumn.setTreePlayerType(null);
                } else if (treeGeneral != null) {
                    if (treeGeneral.getTreePlayerType() == TreePlayerTypeEnum.red) {
                        redDead = false;
                    } else {
                        blueDead = false;
                    }
                }
            }
        }
        if (redDead || blueDead) {
            battleRoundInfo = new BattleRoundInfo();
            battleRoundInfo.setStepId(battleDetail.getStepId());
            battleRoundInfo.setGameOver(true);
            int win = 3;
            if (!redDead) {
                win = 1;
            } else if (!blueDead) {
                win = 2;
            }
            battleRoundInfo.setWin(win);

        }

        return battleRoundInfo;
    }

    public List<Position> getCanSKillAttackPosition(GetCanAttackPositionReq getCanAttackPositionReq) {
        BattleDetail battleDetail = getBattleDetail(getCanAttackPositionReq.getId());

        BattleTreeInfoColumn battleTreeInfoColumn = battleDetail.getTrees()
                .get(getCanAttackPositionReq.getRow())
                .getTreeInfoColumns().get(getCanAttackPositionReq.getColumn());

        BattleTreeInfoColumn newBattleTreeInfoColumn = battleDetail.getTrees()
                .get(getCanAttackPositionReq.getNewRow())
                .getTreeInfoColumns().get(getCanAttackPositionReq.getNewColumn());

        AiLogic aiLogic = new AiLogic(battleDetail.trees, battleTreeInfoColumn.getTreePlayerType());
        return aiLogic.getAttackPosition(null, battleTreeInfoColumn.getPlayerTreeGeneral().getSkillRangeCount(),
                newBattleTreeInfoColumn);
    }
}